﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

using Bootstrap5.Abstractions;

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Rendering;

namespace Bootstrap5;

public class ValidationFeedback<TValue>:BootstrapChildContentComponentBase,IDisposable
{
    private EditContext? _previousEditContext;

    private Expression<Func<TValue>>? _previousFieldAccessor;

    private readonly EventHandler<ValidationStateChangedEventArgs>? _validationStateChangedHandler;

    private FieldIdentifier _fieldIdentifier;

    public ValidationFeedback()
	{
        _validationStateChangedHandler = delegate
          {
              StateHasChanged();
          };
	}

    /// <summary>
    /// Gets the <see cref="EditContext"/> from <see cref="Form"/> component.
    /// </summary>
    [CascadingParameter] EditContext? CurrentEditContext { get; set; }

    [Parameter]public Expression<Func<TValue>> For { get; set; }
	[Parameter] public RenderFragment ValidFeedbackContent { get; set; }

	protected override void OnParametersSet()
	{
		if (CurrentEditContext == null)
		{
			throw new InvalidOperationException($"{GetType()} requires a cascading parameter " + string.Format("of type {0}. For example, you can use {1} inside ", "EditContext", GetType()) + "a Form.");
		}

		if (For == null)
		{
			throw new InvalidOperationException($"{GetType()} requires a value for the " + "For parameter.");
		}

		if (For != _previousFieldAccessor)
		{
			_fieldIdentifier = FieldIdentifier.Create(For);
			_previousFieldAccessor = For;
		}

		if (CurrentEditContext != _previousEditContext)
		{
			DetachValidationStateChangedListener();
			CurrentEditContext.OnValidationStateChanged += _validationStateChangedHandler;
			_previousEditContext = CurrentEditContext;
		}
	}

	protected bool IsValid=> !CurrentEditContext.GetValidationMessages(_fieldIdentifier).Any();

	protected override void BuildRenderTree(RenderTreeBuilder builder)
	{
		if (IsValid && ValidFeedbackContent is not null)
		{
			builder.OpenElement(0, "div");
			BuildCommonAttributes(builder);
			builder.AddContent(3, ValidFeedbackContent);
			builder.CloseElement();
		}
		if (!IsValid)
		{
			foreach (string validationMessage in CurrentEditContext.GetValidationMessages(_fieldIdentifier))
			{
				builder.OpenElement(0, "div");
				BuildCommonAttributes(builder);
				builder.AddContent(3, validationMessage);
				builder.CloseElement();
			}
		}
	}

	protected override void CreateCssClass(ICssClassBuilder builder)
	{
		builder.Add("valid-feedback", IsValid)
			.Add("invalid-feedback")
			;
	}
	//
	// 摘要:
	//     Called to dispose this instance.
	//
	// 参数:
	//   disposing:
	//     true if called within System.IDisposable.Dispose.
	protected virtual void Dispose(bool disposing)
	{
	}

	void IDisposable.Dispose()
	{
		DetachValidationStateChangedListener();
		Dispose(disposing: true);
	}

	private void DetachValidationStateChangedListener()
	{
		if (_previousEditContext != null)
		{
			_previousEditContext!.OnValidationStateChanged -= _validationStateChangedHandler;
		}
	}
}
